package org.codefinger.dao.util;

import java.io.Closeable;
import java.lang.ref.SoftReference;
import java.util.Arrays;

public class TLArrayList implements Closeable {

	private static final ThreadLocal<SoftReference<Object[]>>	LOCAL_BUFFER	= new ThreadLocal<SoftReference<Object[]>>();

	private Object[]											elementData;

	private int													size			= 0;

	public TLArrayList() {

		SoftReference<Object[]> ref = LOCAL_BUFFER.get();

		if (ref != null) {
			elementData = ref.get();
			LOCAL_BUFFER.set(null);
		}

		if (elementData == null) {
			elementData = new Object[10];
		}

	}

	public void add(Object value) {
		ensureExplicitCapacity(size + 1);
		elementData[size++] = value;
	}

	public void back(int size) {
		this.size = size;
	}

	public int size() {
		return size;
	}

	public Object[] toArray() {
		return Arrays.copyOf(elementData, size);
	}

	@SuppressWarnings("unchecked")
	public <T> T[] toArray(T[] a) {
		if (a.length < size) {
			return (T[]) Arrays.copyOf(elementData, size, a.getClass());
		}
		System.arraycopy(elementData, 0, a, 0, size);
		if (a.length > size) {
			a[size] = null;
		}
		return a;
	}

	@Override
	public void close() {
		if (size <= 80) {
			LOCAL_BUFFER.set(new SoftReference<Object[]>(elementData));
		}
	}

	private void ensureExplicitCapacity(int minCapacity) {
		if (minCapacity - elementData.length > 0) {
			grow(minCapacity);
		}
	}

	private void grow(int minCapacity) {
		int oldCapacity = elementData.length;
		int newCapacity = oldCapacity + (oldCapacity >> 1);
		if (newCapacity - minCapacity < 0) {
			newCapacity = minCapacity;
		}
		elementData = Arrays.copyOf(elementData, newCapacity);
	}

}
